#ifndef _MY_DATA_
#define _MY_DATA_
#include <mysql/mysql.h>
#include <condition_variable>
#include <mutex>
#include "util.hpp"
const char* kIp = "0.0.0.0";
const int kPort = 3306;
const char* kUser = "wanku";
const char* kPasswrod = "123456";
const char* kDatabase = "test";

static void MysqlDestory(MYSQL* mysql) {
    if (nullptr != mysql) {
        mysql_close(mysql);
    }
}
static MYSQL* MysqlInit() {
    MYSQL* mysql = mysql_init(NULL);
    if (nullptr == mysql) {
        std::cerr << "init mysql instance fail" << std::endl;
        return nullptr;
    }
    if (nullptr == mysql_real_connect(mysql, kIp, kUser, kPasswrod, kDatabase, kPort, nullptr, 0)) {
        std::cerr << "connect mysql server failed" << std::endl;
        fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(mysql));
        MysqlDestory(mysql);
        return nullptr;
    }
    int ret = mysql_set_character_set(mysql, "utf8");
    if (0 != ret) {
        std::cerr << "set mysql character failed" << std::endl;
        MysqlDestory(mysql);
        return nullptr;
    }
    return mysql;
}

static bool MysqlQuery(MYSQL* mysql, const std::string& sql) {
    int ret = mysql_query(mysql, sql.c_str());
    if (0 != ret) {
        std::cerr << sql << std::endl
                  << mysql_errno(mysql) << std::endl;
        return false;
    }
    return true;
}

class TableVideo {
   private:
    MYSQL* mysql_ = nullptr;
    std::mutex mutex_;

   public:
    TableVideo() {
        mysql_ = MysqlInit();
        if (nullptr == mysql_) {
            exit(-1);
        }
        std::cout << "数据库初始成功" << std::endl;
    };
    ~TableVideo() {
        MysqlDestory(mysql_);
    }
    bool Insert(const Json::Value& video) {
        std::string sql;
        sql = "insert into tb_video values(null, '" + video["name"].asString() + "','" +
              video["info"].asString() + "','" + video["video"].asString() + "','" + video["image"].asString() + "');";
        return MysqlQuery(mysql_, sql);
    }
    bool Update(const int video_id, const Json::Value& video) {
        std::string sql;
        sql = "update tb_video set name='" + video["name"].asString() + "', info='" +
              video["info"].asString() + "' where id=" + std::to_string(video_id) + ";";
        return MysqlQuery(mysql_, sql);
    }
    bool Delete(const int video_id) {
        std::string sql;
        sql = "delete from tb_video where id=" + std::to_string(video_id) + ";";
        return MysqlQuery(mysql_, sql);
    }
    bool SelectAll(Json::Value* videos) {
        std::string sql = "select * from tb_video";
        MYSQL_RES* res = nullptr;
        {
            std::unique_lock<std::mutex> locker(mutex_);
            bool ret = MysqlQuery(mysql_, sql);
            if (false == ret) {
                return false;
            }
            res = mysql_store_result(mysql_);
        }
        if (res == nullptr) {
            std::cerr << "mysql store result failed!" << std::endl;
            return false;
        }
        int num_rows = mysql_num_rows(res);
        for (int i = 0; i < num_rows; ++i) {
            MYSQL_ROW row = mysql_fetch_row(res);
            Json::Value video;
            video["id"] = atoi(row[0]);
            video["name"] = row[1];
            video["info"] = row[2];
            video["video"] = row[3];
            video["image"] = row[4];
            videos->append(video);
        }
        mysql_free_result(res);
        return true;
    };

    bool SelectOne(int video_id, Json::Value* video) {
        std::string sql = "select * from tb_video where id =" + std::to_string(video_id) + ";";
        MYSQL_RES* res = nullptr;
        {
            std::unique_lock<std::mutex> locker(mutex_);
            bool ret = MysqlQuery(mysql_, sql);
            if (false == ret) {
                return false;
            }
            res = mysql_store_result(mysql_);
        }
        if (res == nullptr) {
            std::cerr << "mysql store result failed!" << std::endl;
            return false;
        }
        int num_rows = mysql_num_rows(res);
        if (num_rows != 1) {
            std::cerr << "no data!" << std::endl;
            mysql_free_result(res);
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        (*video)["id"] = video_id;
        (*video)["name"] = row[1];
        (*video)["info"] = row[2];
        (*video)["video"] = row[3];
        (*video)["image"] = row[4];
        mysql_free_result(res);
        return true;
    }
    bool SelectLike(const std::string& key, Json::Value* videos) {
        std::string sql = "select * from tb_video where name like '%" + key + "%'";
        MYSQL_RES* res = nullptr;
        {
            std::unique_lock<std::mutex> locker(mutex_);
            bool ret = MysqlQuery(mysql_, sql);
            if (false == ret) {
                return false;
            }
            res = mysql_store_result(mysql_);
        }
        if (res == nullptr) {
            std::cerr << "mysql store result failed!" << std::endl;
            return false;
        }
        int num_rows = mysql_num_rows(res);
        for (int i = 0; i < num_rows; ++i) {
            MYSQL_ROW row = mysql_fetch_row(res);
            Json::Value video;
            video["id"] = atoi(row[0]);
            video["name"] = row[1];
            video["info"] = row[2];
            video["video"] = row[3];
            video["image"] = row[4];
            videos->append(video);
        }
        mysql_free_result(res);
        return true;
    }
};

#endif